package connectfour;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.appengine.api.channel.ChannelMessage;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;

@PersistenceCapable
public class Game implements Serializable{
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	Key key;
	
	@Persistent
	Key host; 
	
	@Persistent
	Key opponent;
	
	@Persistent
	User userHost;
	
	@Persistent
	User userOpponent;
	
	@Persistent
	int turn;  // 0 -> not playing, odd-> host, even-> opponent
	
	@Persistent
	int winner;  // 0 -> no winner yet, 1 -> p1 has won, 2 -> p2 has won
	
	@Persistent
	boolean over;  // true if game is ended (regardless if won or aborted)
	
	@Persistent
	Date date;  // date the game was begun
	
	@Persistent
	ArrayList<Integer> grid;
	
	@Persistent
	ArrayList<Integer> numPieces; // stores the number of pieces currently in a row
	                              // so that we know which row a piece falls down to
	@Persistent
	int lastMove;                 // the player that made the last move
	
	public Game(Key h, Date d){
		host = h;
		turn = 0;
		date = d;
		over = false;
		grid = new ArrayList<Integer>(64);
		for(int i = 0; i < 64; i++){
			grid.add(i, 0);
		}
		
		numPieces = new ArrayList<Integer>(64);
		for(int i = 0; i < 8; i++){
			numPieces.add(i, 0);
		}
		
		lastMove = 0;
	}
	public Key getKey(){ return key; }
	public Key getHost(){ return host; }
	public Key getOpponent(){ return opponent; }
	public int getTurn(){ return turn; }
	public Date getDate() { return date; }
	public ArrayList<Integer> getGrid(){ return grid; }
	public int getValue(int c, int r) {	return grid.get(c + 8*r); }
	public ArrayList<Integer> getNumPieces(){ return numPieces; }
	public boolean isOver() { return over; }
	public int getWinner() { return winner; }
	public int getLastMove() { return lastMove; }
	public User getUserHost() { return userHost; }
	public User getUserOpponent() { return userOpponent; }
	
	
	public void setUserHost(User h) { userHost = h; }
	public void setUserOpponent(User o) { userOpponent = o; }
	public void setWinner(int w) { winner = w; } 
	public void setHost(Key h){ host = h; }
	public void setOpponent(Key o){ opponent = o; }
	public void setTurn(int t){ turn = t; }
	public void incTurn(){ turn++; }
	public void setDate(Date d) { date = d; }
	public void setGrid(ArrayList<Integer> g){ grid = g; }
	public void setGrid(int c, int v){ 
		int r = numPieces.get(c);
		grid.set(c + 8*r, v); 
		numPieces.set(c, numPieces.get(c) + 1);
		lastMove = c + 8*r;
	}
	public void setNumPieces(ArrayList<Integer> n){ numPieces = n; }
	public void incNumPieces(int c) { numPieces.set(c, numPieces.get(c) + 1); }
	public void setLastMove(int l) { lastMove = l; }

	public void isOver(boolean o) { over = o; }
	
	
	  public String getChannelKey(String user) {
	    return user + KeyFactory.keyToString(key);
	  }
	
	  private void sendUpdateToUser(Key user) {
	    if (user != null) {
	      ChannelService channelService = ChannelServiceFactory.getChannelService();
	      String channelKey = getChannelKey(Long.toString(user.getId()));
	      channelService.sendMessage(new ChannelMessage(channelKey, "update"));
	    }
	  }
	
	  public void sendUpdateToClients() {
	    sendUpdateToUser(host);
	    sendUpdateToUser(opponent);
	  }
	  
	  public boolean hasWon(int p){
		  int a, b, c;
		  for(int i = 0; i < 64; i++){
			  if(grid.get(i) == p){
				  // up
				  if(i < 40){
					  a = grid.get(i + 8);
					  b = grid.get(i + 2*8);
					  c = grid.get(i + 3*8);
					  if(p == a && p == b && p == c){
						  return true;
					  }
				  } 
				  //right
				  if((i % 8) < 5){
					  a = grid.get(i + 1);
					  b = grid.get(i + 2);
					  c = grid.get(i + 3);
					  if(p == a && p == b && p == c){
						  return true;
					  }
				  }
				  //diag up right
				  if((i % 8) < 5 && i < 40){
					  a = grid.get(i + 9);
					  b = grid.get(i + 2*9);
					  c = grid.get(i + 3*9);
					  if(p == a && p == b && p == c){
						  return true;
					  }
				  }
				  //diag up left
				  if((i % 8) > 2 && i < 40){
					  a = grid.get(i + 7);
					  b = grid.get(i + 2*7);
					  c = grid.get(i + 3*7);
					  if(p == a && p == b && p == c){
						  return true;
					  }
				  }
			  }			  
		  }
		  return false;
	  }
} 
